package wechat

import (
	"encoding/xml"
	"errors"
	"go-init/lib/log"
	"strconv"
	"time"
)

//UnifiedOrderReq 统一下单请求
type UnifiedOrderReq struct {
	Appid          string `xml:"appid"`            //公众账号ID
	MchID          string `xml:"mch_id"`           //商户号
	DeviceInfo     string `xml:"device_info"`      //设备号
	NonceStr       string `xml:"nonce_str"`        //随机字符串
	Sign           string `xml:"sign"`             //签名
	SignType       string `xml:"sign_type"`        //签名类型  MD5
	Body           string `xml:"body"`             //商品描述
	Detail         string `xml:"detail"`           //商品详情
	Attach         string `xml:"attach"`           //附加数据
	OutTradeNo     string `xml:"out_trade_no"`     //商户订单号
	FeeType        string `xml:"fee_type"`         //标价币种  CNY
	TotalFee       int    `xml:"total_fee"`        //标价金额
	SpbillCreateIP string `xml:"spbill_create_ip"` //终端IP
	TimeStart      string `xml:"time_start"`       //交易起始时间
	TimeExpire     string `xml:"time_expire"`      //交易结束时间
	GoodsTag       string `xml:"goods_tag"`        //订单优惠标记
	NotifyURL      string `xml:"notify_url"`       //通知地址
	TradeType      string `xml:"trade_type"`       //交易类型
	ProductID      string `xml:"product_id"`       //商品ID
	LimitPay       string `xml:"limit_pay"`        //指定支付方式
	Openid         string `xml:"openid"`           //用户标识
	Receipt        string `xml:"receipt"`          //电子发票入口开放标识
	SceneInfo      string `xml:"scene_info"`       //场景信息
}

//UnifiedOrderResp 统一下单响应
type UnifiedOrderResp struct {
	ReturnCode string `xml:"return_code"`  //返回状态码  SUCCESS
	ReturnMsg  string `xml:"return_msg"`   //返回信息	OK
	Appid      string `xml:"appid"`        //公众账号ID
	MchID      string `xml:"mch_id"`       //商户号
	DeviceInfo string `xml:"device_info"`  //设备号
	NonceStr   string `xml:"nonce_str"`    //随机字符串
	Sign       string `xml:"sign"`         //sign
	ResultCode string `xml:"result_code"`  //业务结果 SUCCESS
	ErrCode    string `xml:"err_code"`     //错误代码
	ErrCodeDes string `xml:"err_code_des"` //错误代码描述
	PrepayID   string `xml:"prepay_id"`    //预支付交易会话标识
	TradeType  string `xml:"trade_type"`   //交易类型
	CodeURL    string `xml:"code_url"`     //二维码链接
}

//UnifiedOrderCallback 统一下单回调
type UnifiedOrderCallback struct {
	ReturnCode         string `xml:"return_code"`          //返回状态码  SUCCESS
	ReturnMsg          string `xml:"return_msg"`           //返回信息	OK
	Appid              string `xml:"appid"`                //公众账号ID
	MchID              string `xml:"mch_id"`               //商户号
	DeviceInfo         string `xml:"device_info"`          //设备号
	NonceStr           string `xml:"nonce_str"`            //随机字符串
	Sign               string `xml:"sign"`                 //sign
	SignType           string `xml:"sign_type"`            //sign
	ResultCode         string `xml:"result_code"`          //业务结果 SUCCESS
	ErrCode            string `xml:"err_code"`             //错误代码
	ErrCodeDes         string `xml:"err_code_des"`         //错误代码描述
	Openid             string `xml:"openid"`               //用户标识
	IsSubscribe        string `xml:"is_subscribe"`         //是否关注公众账号
	TradeType          string `xml:"trade_type"`           //交易类型
	BankType           string `xml:"bank_type"`            //付款银行
	TotalFee           int    `xml:"total_fee"`            //标价金额
	SettlementTotalFee int    `xml:"settlement_total_fee"` //应结订单金额
	FeeType            string `xml:"fee_type"`             //标价币种
	CashFee            int    `xml:"cash_fee"`             //现金支付金额
	CashFeeType        string `xml:"cash_fee_type"`        //现金支付金额
	CouponFee          int    `xml:"coupon_fee"`           //代金券金额
	CouponCount        int    `xml:"coupon_count"`         //代金券使用数量
	CouponType0        string `xml:"coupon_type_0"`        //代金券使用数量
	CouponID0          string `xml:"coupon_id_0"`          //代金券使用数量
	CouponFee0         int    `xml:"coupon_fee_0"`         //代金券使用数量
	TransactionID      string `xml:"transaction_id"`       //微信支付订单号
	OutTradeNo         string `xml:"out_trade_no"`         //商户订单号
	Attach             string `xml:"attach"`               //附加数据
	TimeEnd            string `xml:"time_end"`             //支付完成时间
}

func (w *Wx) UnifiedOrderMiniapp(uor *UnifiedOrderReq) (res map[string]interface{}, err error) {
	uor.Appid = w.config.MiniAppid
	uor.TradeType = "JSAPI"
	uor.MchID = w.config.Mchid
	uor.NonceStr = randomStr(32)
	m := structToMap(uor)
	uor.Sign = wxpayCalcSign(m, w.config.Mchkey)
	respBytes, err := request(uor, unifiedOrderURL)
	if err != nil {
		log.Info(err)
		return
	}
	xmlResp := UnifiedOrderResp{}
	err = xml.Unmarshal(respBytes, &xmlResp)
	if err != nil {
		log.Info("解析返回body错误", err)
		return
	}
	if xmlResp.ReturnCode == "FAIL" {
		log.Info("微信支付统一下单不成功，原因:", xmlResp.ReturnMsg)
		err = errors.New(xmlResp.ReturnMsg)
		return
	}
	if xmlResp.ResultCode == "FAIL" {
		log.Info("微信支付统一下单不成功，原因:", xmlResp.ErrCodeDes, " 错误码:", xmlResp.ErrCode)
		err = errors.New(xmlResp.ErrCodeDes)
		return
	}
	timeStamp := strconv.FormatInt(time.Now().Unix(), 10)
	res = make(map[string]interface{})
	res["package"] = "prepay_id=" + xmlResp.PrepayID
	res["appId"] = uor.Appid
	res["timeStamp"] = timeStamp
	res["nonceStr"] = uor.NonceStr
	res["signType"] = "MD5"
	res["paySign"] = wxpayCalcSign(res, w.config.Mchkey)
	res["prepay_id"] = xmlResp.PrepayID
	return
}

//UnifiedOrderCallbackVerify 统一下单回调验证
func (w *Wx) UnifiedOrderCallbackVerify(body []byte) (uoc *UnifiedOrderCallback, ok bool, err error) {
	err = xml.Unmarshal(body, &uoc)
	if err != nil {
		return
	}
	reqMap := structToMap(uoc)
	var secret string
	if w.config.Mchid == uoc.MchID {
		secret = w.config.Mchkey
	} else {
		secret = w.config.MchkeyApp
	}
	ok = false
	if verifySign(reqMap, uoc.Sign, secret) {
		ok = true
	}
	return
}

//NotifyResp 微信支付通知微信服务器消息
type NotifyResp struct {
	ReturnCode string `xml:"return_code"`
	ReturnMsg  string `xml:"return_msg"`
}
